Implementing Volume Transaction Licensing

To implement the volume transaction licensing for your application, perform the following steps:

1. Decide a notation to identify the following in a license:

2.The various limits, such as the transaction limit, duration limit, and any overdraft and alert levels that you want to apply.

3.An identifier (for example sequence number) to differentiate between the multiple licenses of same feature and version.

For example, the string <software vendor-specific identifier>:V:1000:100:200 denotes a policy based on the number of transactions/operations, where:

<software vendor specific identifier> = The software vendor specific identifier of a license. This is optional and useful when multiple licenses of same feature/version exist

1000 = The maximum number of transactions that are allowed

100 = The alert level (when only 100 transactions are remaining, an alert is to be generated)

200 = The overdraft amount that a user can use after exhausting the maximum limit

Similarly, <software vendor-specific identifier>:D:311208:30:15, denotes a policy based on the dates and duration:

<software vendor-specific identifier> = The software vendor specific identifier of a license. This is optional and useful when multiple licenses of same feature/version exist

311208 = The maximum allowed date, which is 31st December 2008

30 = The alert level (30 days before the expiry of the duration limit on which an alert is to be generated)

15 = The next 15 days are the overdraft that a user can use after exhausting the maximum duration

4. Generate a license with the policy. The volume transaction limits are included in the vendor information field of a license. An example is shown below in the lscgen (license generator) screenshot:

Figure 1: Specifying Vendor Information in lscgen

5.In your application code, enumerate all the licenses (in case multiple licenses of the same feature/version co-exists) using VLSgetLicenseInfo API function.

The sequence number or any other software vendor-specific identifier helps to differentiate the license.

Once decided, the application needs to keep a track of the license in use (using a software vendor specific identifier, such as a sequence number) and the policy enforced. You need to request a particular feature and use the handle obtained to call the following volume transaction licensing API functions.

The following table summarizes the functions prototyped in lserv.h:

Function Description
VLSgetConsumeLimit Returns the current limit stored in the volume transaction licensing database for a particular license.
VLSsetConsumeLimit Increases, decreases, or resets the limit in the volume transaction licensing database for a particular license.
VLSgetContextData Returns the current context data stored in the volume transaction licensing database for a particular license.
VLSsetContextData Sets the current context data (string) with the data passed for a particular license.

NOTE   In the case of a standalone applications, you need to ensure that the context data is synchronized for the various processes. For network applications, this synchronization is handled by the License Manager.

A prototype of a calling sequence is provided below; however, for details about each API function and its parameters, you can see the Sentinel RMS API Reference Guide.

You can also see the demo file of volume transaction licensing using API calls in vtlapp.c, available in the following folder: <installdir>\Samples\C\Src.

VLS_INITIALIZE()
/* Fill the size parameter of the featureInfo struct.Else, the query may not obtain complete data. */ 
licenseInfo.structSz = sizeof(licenseInfo);
rc = VLSgetLicenseInfo(FEATURE_NAME,
                       VERSION,
                       -1,
                        NULL,
                       0,
                        0,
                         &licenseInfo);
 
/* If there are more than 1 license for a particular feature/version, iterate through all the licenses using this API and determine the correct license using the identifier specified in software vendor-info while generating the license */
 
  if(rc == LS_SUCCESS)
  {
   /* Obtains the policy information. This should be interpreted by
your application*/
    strncpy(policy_data, licenseInfo.vendor_info, VLS_VENINFOLEN);
     volume_info = strtok( policy_data, ";" );
         /* Obtains the individual limits */ 
     strtok( volume_info, ":" );
    volume_limit = atoi(strtok( NULL, ":" ));
  /* Obtains the alert level. Determines prior
  to how many transactions the warnings are generated*/ 
    warning_amount = atoi(strtok( NULL, ":" ));
  /* Obtains the overdraft value. Determines how many transactions   after the expiration of limit the feature is allowed to run */
    grace_amount = atoi(strtok( NULL, ":" ));
  }
/* Obtains a license */
VLS_REQUEST( FEATURE_NAME, "1.0", &handle);
currval=0;
type=VLS_LIMIT_TYPE_VOLUME;
rc = VLSgetConsumeLimit(handle,type,&currval,NULL);
 
switch(rc)
{
   case LS_SUCCESS: 
        printf("\ncurrent volume limit is %d", currval);
      break;
     case VLS_NO_RECORDS_FOUND:
     /* No limit set in the database for this feature & version */ 
         printf("\nNo limit set in the database for this feature & version");
        break;
    case VLS_OPERATION_NOT_SUCCESSFUL: 
           printf("\nGet operation not successful");
}
/*Generate Warnings*/ 
if( (volume_limit > currval) && ((volume_limit - currval) <= warning_amount))
{
       printf("\nThe current volume limit is reaching the maximum allowed limit");
}
   /* Check if the current limit has exceeded then allow the feature to run till the grace limit */
if(currval == (volume_limit + grace_amount))
{
   printf(LIMIT_EXHAUSTED_MESSAGE);
   /* At this point, the application may decide to take appropriate action. For example, do not allow any operations licensed by volume limits*/
       VLS_RELEASE(handle); 
   VLS_CLEANUP();
}
/***** Renew license key (license heartbeat) *****/
VLS_UPDATE(handle);
/* Now increment the volume limit by INCREMENT_VAL units. This implies that the application will perform an operation which consumes INCREMENT_VAL units
*/
val = INCREMENT_VAL;
type=VLS_LIMIT_TYPE_VOLUME;
optype=VLS_SET;
if(val > ((volume_limit + grace_amount)- currval))
val = (volume_limit + grace_amount)- currval;
if(val == 0)
{
    printf(LIMIT_EXHAUSTED_MESSAGE);
   VLS_RELEASE(handle);
   VLS_CLEANUP();
}
/*Incrementing the volume limit*/
rc = VLSsetConsumeLimit(handle,type,optype,&val,NULL);
switch(rc)
{
   case LS_SUCCESS: 
     /*Limit set Successfully*/ 
     break;
   case VLS_NEW_RECORD_FOUND:
     while( rc == VLS_NEW_RECORD_FOUND )
           {
              type=VLS_LIMIT_TYPE_VOLUME;
       optype=VLS_SET;
        rc = VLSsetConsumeLimit(handle,type,optype,&val,NULL);
          if( rc == VLS_OPERATION_NOT_SUCCESSFUL)
          /*Set operation failed*/
                if( rc == VLS_NEW_RECORD_FOUND)
       { 
      /* A newer value has been found in database since the last read  operation was performed. The new value is returned in the "val" parameter. The application should check if the current limit does not exceed the policy limits and again try to increment the database with the required value */
         printf("\nA newer limit value found %d\n",val);
       /*Check if the current limit does not exceed the policy limits*/ 
          if(val >= volume_limit)
                  {
            printf("\nThe current Limit equals or exceeds the policy Limits");
/*At this point, the application may decide to take appropriate action.
For example, do not allow any operations licensed by volume limits*/
          }
        }
        }
     break;
case VLS_OPERATION_NOT_SUCCESSFUL: 
   printf("\nSet operation not successful");
}
/*Perform an operation which consumes say, INCREMENT_VAL Volume limits*/ 
VLS_RELEASE(handle); 
VLS_CLEANUP();